// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Emergent Game Technologies and may not 
// be copied or disclosed except in accordance with the terms of that 
// agreement.
//
//      Copyright (c) 1996-2008 Emergent Game Technologies.
//      All Rights Reserved.
//
// Emergent Game Technologies, Chapel Hill, North Carolina 27517
// http://www.emergent.net

#ifndef NITSET_H
#define NITSET_H

// This template class implements an unordered set. Because it does not
// set removed elements to 0, it should not be used for smart pointers.
//
// Note that there is an additional template argument, TAlloc.
// This class must declare static functions matching the following prototypes:
//
//      static T* Allocate(unsigned int uiNumElements)
//      static void Deallocate(T* pArray)

#include <GnRTLib.h>
#include <GnMemObject.h>

#include "GnTCollection.h"

template <class T, class TAlloc> class GnTSet  : public GnMemObject
{
public:
    GnTSet(unsigned int uiInitialSize = 0);
    ~GnTSet();

    unsigned int GetSize() const;
    T *GetBase() const;
    const T& GetAt(unsigned int uiIndex) const;
    T& GetAt(unsigned int uiIndex);
    unsigned int Add(const T& element);
    unsigned int AddUnique(const T& element); // Slow. Use with caution.
    void RemoveAt(unsigned int uiIndex);
    void OrderedRemoveAt(unsigned int uiIndex); // Preserve order.
    void ReplaceAt(unsigned int uiIndex, const T& element);
    void RemoveAll();
    int Find(const T& element) const; // Slow. Use with caution.
    
    // Resize the array to be the number of used items.
    void Realloc();

    // This method clamp the size to being >= m_uiUsed.
    void Realloc(unsigned int uiNewSize);

    // This method will reallocate only if the new size is greater than
    // the size already allocated.
    void ReallocNoShrink(unsigned int uiNewSize);

    // Get the maximum number of items before a reallocation
    // is forced.
    unsigned int GetAllocationSize() const;
protected: 
    T *m_pBase;
    unsigned int m_uiAlloced;
    unsigned int m_uiUsed;

private:
    // To prevent an application from inadvertently causing the compiler to
    // generate the default copy constructor or default assignment operator,
    // these methods are declared as private. They are not defined anywhere,
    // so code that attempts to use them will not link.
    GnTSet(const GnTSet&);
    GnTSet& operator=(const GnTSet&);
};

template <class T> class GnTObjectSet: 
    public GnTSet<T, GnTNewInterface<T> >
{
public:
    GnTObjectSet(unsigned int uiInitialSize = 0);
};

template <class T> class GnTPrimitiveSet: 
    public GnTSet<T, GnTMallocInterface<T> >
{
public:
    GnTPrimitiveSet(unsigned int uiInitialSize = 0);
};


typedef GnTPrimitiveSet<unsigned int> GnUnsignedIntSet;
typedef GnTPrimitiveSet<unsigned short> GnUnsignedShortSet;
typedef GnTPrimitiveSet<float> GnFloatSet;

#include "GnTSet.inl"

#endif // NITSET_H
